﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;

using System.Windows.Interop;

using forms = System.Windows.Forms;
using Size = System.Drawing.Size;

using ToDo_CSharp.Properties;

namespace ToDo_CSharp
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		public MainWindow()
		{
			InitializeComponent();
		}

		#region variables
		private delegate void NoArgDelegate();

		private IntPtr Handle { get { return new WindowInteropHelper(this).Handle; } }
		public FileSystemWatcher TodoWatcher { get; set; }
		
		private forms.NotifyIcon _notifyIcon;

		private string TodoFileFullPath
		{
			get
			{
				if (string.IsNullOrEmpty(_todoFilePath))
					_todoFilePath = Path.Combine(Settings.Default.ToDoFilePath, Settings.Default.ToDoFileName);

				return _todoFilePath;
			}
		}
		private string _todoFilePath;

		#endregion
		#region form events

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			SetWindowLocation();
			Win32.HideFromAltTab(Handle);

			Width = SystemParameters.FullPrimaryScreenWidth;
			Top = SystemParameters.FullPrimaryScreenHeight - Height + 22;

			CreateNotifyIcon();
			VerifyToDoFileLocation();

			if (File.Exists(TodoFileFullPath))
			    fillWrapPanel();

			createFileSystemWatcher();
		}

		private void Window_StateChanged(object sender, EventArgs e)
		{
			if (WindowState == WindowState.Minimized)
				WindowState = WindowState.Normal;
		}

		private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			if (Visibility == Visibility.Visible)
				SetWindowLocation();
		}

		private void openMenuItem_Click(object sender, EventArgs e)
		{
			if (!File.Exists(TodoFileFullPath))
				File.Create(TodoFileFullPath).Close();

			Process.Start(TodoFileFullPath);
		}

		private void configurationMenuItem_Click(object sender, EventArgs e)
		{
			var config = new Configuration { Owner = this };

			Visibility = Visibility.Hidden;

			// by showing the dialog, it thrusts the stuff to the front.
			config.ShowDialog();

			Visibility = Visibility.Visible;
			fillWrapPanel();
		}

		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_notifyIcon.Dispose();

			Close();
		}


		#endregion

		#region private functions
		private void SetWindowLocation()
		{
			if (Settings.Default.TopMost)
				Win32.SetWindowInFront(Handle);
			else
				Win32.SetWindowInBack(Handle);
		}

		private void CreateNotifyIcon()
		{
			_notifyIcon = new forms.NotifyIcon { Text = "ToDo", Icon = new Icon("report.ico"), Visible = true };

			var contextMenu = new forms.ContextMenuStrip { Name = "contextMenu" };
			var exitToolStripMenuItem = new forms.ToolStripMenuItem { Name = "exitToolStripMenuItem1", Text = "Exit" };
			var configurationMenuItem = new forms.ToolStripMenuItem { Name = "configurationMenuItem", Text = "Options" };
			var openMenuItem = new forms.ToolStripMenuItem { Name = "openMenuItem", Text = "Open ToDo" };

			// contextMenu
			contextMenu.Items.AddRange(new forms.ToolStripItem[] { openMenuItem, configurationMenuItem, exitToolStripMenuItem });
			contextMenu.Size = new Size(155, 114);

			exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
			configurationMenuItem.Click += configurationMenuItem_Click;
			openMenuItem.Click += openMenuItem_Click;
			_notifyIcon.ContextMenuStrip = contextMenu;
		}

		private void VerifyToDoFileLocation()
		{
			if (string.IsNullOrEmpty(Settings.Default.ToDoFileName) || string.IsNullOrEmpty(Settings.Default.ToDoFilePath))
			{
				Settings.Default.ToDoFileName = "todo.txt";
				Settings.Default.ToDoFilePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
				Settings.Default.Save();
			}

			if (!File.Exists(TodoFileFullPath))
			{
				configurationMenuItem_Click(this, null);
			}
		}

		private void createFileSystemWatcher()
		{
			TodoWatcher = new FileSystemWatcher { Path = Settings.Default.ToDoFilePath, Filter = Settings.Default.ToDoFileName };

			TodoWatcher.Changed += todoWatcher_Changed;
			TodoWatcher.Created += todoWatcher_Changed;

			TodoWatcher.EnableRaisingEvents = true;
		}

		private void todoWatcher_Changed(object sender, FileSystemEventArgs e)
		{
			wpTodo.Dispatcher.Invoke(new NoArgDelegate(fillWrapPanel));
		}

		private void fillWrapPanel()
		{
			// does file exist and not in use?
			string todoFileText = string.Empty;

			if (File.Exists(TodoFileFullPath))
			{
				while (FileInUse(TodoFileFullPath))
					Thread.Sleep(50);
				
				todoFileText = File.ReadAllText(TodoFileFullPath);
			}

			wpTodo.Children.Clear();
			string[] items = Regex.Split(todoFileText, Environment.NewLine);

			foreach (string item in items)
				wpTodo.Children.Add(CreateLabel(item));
		}

		private Label CreateLabel(string item)
		{
			var txt = new Label
			{
				Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(0, 0, 0, 0)),
				Foreground = new SolidColorBrush(Settings.Default.FontForeColor),
				AllowDrop = false,

				Focusable = false,
				BorderThickness = new Thickness(0),
				Content = item
			};
			txt.MouseDown += txt_MouseDown;

			if (Settings.Default.FontGlowColor.A != 0)
				txt.BitmapEffect = new OuterGlowBitmapEffect
				{
					GlowColor = Settings.Default.FontGlowColor,
					GlowSize = 7
				};

			return txt;
		}

		void txt_MouseDown(object sender, MouseButtonEventArgs e)
		{
			SetWindowLocation();
		}

		public static bool FileInUse(string path)
		{
			try
			{
				using (File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				if (ex.Message.Contains("The process cannot access the file"))
					return true;

				throw;
			}
		}
		#endregion
	}
}